<?php

namespace App\Kuafu\Pay\Jobs;

use App\Kuafu\Pay\Model\MyPayRefundCallback;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Model\RefundStreamModel;
use App\Library\FeiShu\SendFs;
use GuzzleHttp\Client;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class PayRefundCallback implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 5; //尝试 5 次

    const QUEUE_NAME = '{RMS-API-PAY-REFUND-CALLBACK}';

    private string $callbackUrl;
    private int    $operateType;
    private string $orderId;
    private string $payNo = '';
    private string $refundNo = '';

    const DELAY_TIME = [
        1 => 10,
        2 => 30,
        3 => 60,
        4 => 600,
        5 => 1800,
    ];

    /**
     * Create a new job instance.
     * @param string $callbackUrl
     * @return void
     */
    public function __construct(string $callbackUrl, int $operateType, string $orderId, string $payRefundNo)
    {
        $this->callbackUrl = $callbackUrl;
        $this->operateType = $operateType;
        $this->orderId     = $orderId;
        if ($this->operateType == PayStreamModel::OPERATE_TYPE_PAY) {
            $this->payNo = $payRefundNo;
        } elseif ($this->operateType == PayStreamModel::OPERATE_TYPE_REFUND) {
            $this->refundNo = $payRefundNo;
        }
    }

    public function handle()
    {
        Log::info("PayRefundCallback........{$this->attempts()}", [
            'callbackUrl' => $this->callbackUrl,
            'operateType' => $this->operateType,
            'orderId'     => $this->orderId,
        ]);

        if ($this->operateType == PayStreamModel::OPERATE_TYPE_PAY) {
            $pay = PayStreamModel::getDataByPayNo($this->payNo);

            $amount = $pay->payPrice;
            $payNo  = $pay->payNo;
            $bizId  = $pay->bizId;
            $payChannel = $pay->payChannel;

        } elseif ($this->operateType == PayStreamModel::OPERATE_TYPE_REFUND) {
            $refund       = RefundStreamModel::query()
                                             ->where('orderId', $this->orderId)
                                             ->where('refundNo', $this->refundNo)
                                             ->first();
            $amount       = $refund->refundPrice;
            $payNo        = $refund->payNo;
            $refundNo     = $refund->refundNo;
            $refundStatus = $refund->refundStatus;
            $payChannel   = $refund->refundChannel;
            $bizId        = '';

        } else {
            Log::info("PayRefundCallback....ERROR operateType:{$this->operateType}");
            return;
        }

        $param = array_filter([
            'operateType'  => $this->operateType,
            'orderId'      => $this->orderId,
            'amount'       => $amount,
            'payNo'        => $payNo,
            'refundNo'     => $refundNo ?? null,
            'refundStatus' => $refundStatus ?? null,
            'bizId'        => $bizId ?? null,
            'payChannel'   => $payChannel ?? null,
        ]);
        $id    = MyPayRefundCallback::addData($this->callbackUrl, $this->attempts(), $param);

        $response = (new Client([
            'timeout' => 10,
        ]))->post($this->callbackUrl, ['json' => $param]);

        $response = json_decode($response->getBody()->getContents(), true) ?? [];
        MyPayRefundCallback::editResponseData($id, json_encode($response));

        if ($this->attempts() >= $this->tries) {
            SendFs::newRobot()->setTitleContent('己方内部服务支付回调失败',
                json_encode(array_merge($param, ['callbackUrl' => $this->callbackUrl]), JSON_UNESCAPED_UNICODE))->send();
            $this->delete();
        }

        if (!isset($response['code']) || $response['code'] != 200) {
            $this->release(self::DELAY_TIME[$this->attempts()] ?? 0);
        }
    }
}
